/**
 * 
 */
package net.xerllent.security;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;


/**
 * @author sxh
 * @date 
 * @describe 安全信息审核类
 */
public class XSSSecurityFilter implements Filter{

	private static Logger logger = Logger.getLogger(XSSSecurityFilter.class);
	
	/**
	 * 销毁操作
	 */
	public void destroy() {
		logger.info("XSSSecurityFilter destroy() begin");
		XSSSecurityManager.destroy();
		logger.info("XSSSecurityFilter destroy() end");
	}

	/**
	 * 安全审核
	 * 读取配置信息
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// 判断是否使用HTTP
        checkRequestResponse(request, response);
        // 转型
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // http信息封装类
		XSSHttpRequestWrapper xssRequest = null; // new XSSHttpRequestWrapper(httpRequest,null);
		
		//第一步:看是否在检查扩展名集合里
		String p=httpRequest.getServletPath();
		if(XSSSecurityManager.EXTENTIONS!=null){//扩展名集合不为空,则匹配的需要查
			String p0=p.toLowerCase();
			boolean  hasext=false;
			for(String e:XSSSecurityManager.EXTENTIONS){
				if(p0.endsWith(e)){//扩展名匹配
					hasext=true;
					//第二步:看是否是忽略的url
					if(XSSSecurityManager.EXCLUDEMAP!=null){//有忽略的
						boolean  hasurl=false;
						for(Entry<String, Set<String>> en:XSSSecurityManager.EXCLUDEMAP.entrySet()){
							String url=en.getKey();
							if(p.startsWith(url)){//属于忽略的url
								hasurl=true;
								
								//第三步:看是否是忽略的params
								Set<String> params=en.getValue();
								if(params!=null){//不为空,则实施参数过滤
									xssRequest = new XSSHttpRequestWrapper(httpRequest,params);
									
								}else{//为空,则跳过该url
									chain.doFilter(request, response);
									return;
								}
								break;
							}
						}
						
						//不属于忽略的,都需要过滤
						if(!hasurl){
							xssRequest = new XSSHttpRequestWrapper(httpRequest,null);
						}
						
						
					}else{//没有忽略的则都需要过滤
						xssRequest = new XSSHttpRequestWrapper(httpRequest,null);
					}
					break;
				}
			}
			
			//没有匹配的扩展名,则跳过该url
			if(!hasext){
				chain.doFilter(request, response);
				return;				
			}
			
		}else{//扩展名集合为空则都需要查
			xssRequest = new XSSHttpRequestWrapper(httpRequest,null);
		}
		
		
        // 对request信息进行封装并进行校验工作，若校验失败（含非法字符），根据配置信息进行日志记录和请求中断处理
        if(xssRequest.validateParameter(httpResponse)){
        	if(XSSSecurityConfig.IS_LOG){
        		// 记录攻击访问日志
        		// 可使用数据库、日志、文件等方式
        	}
        	if(XSSSecurityConfig.IS_CHAIN){
        		httpRequest.getRequestDispatcher(XSSSecurityCon.FILTER_ERROR_PAGE).forward( httpRequest, httpResponse);
        		return;
    		}
        }
        chain.doFilter(xssRequest, response);
	}
	

	/**
	 * 初始化操作
	 */
	public void init(FilterConfig filterConfig) throws ServletException {
		XSSSecurityManager.init(filterConfig);
	}

	/**
     * 判断Request ,Response 类型
     * @param request ServletRequest
     * @param response ServletResponse
     * @throws ServletException 
     */
    private void checkRequestResponse(ServletRequest request, ServletResponse response) throws ServletException {
        if (!(request instanceof HttpServletRequest)) {
            throw new ServletException("Can only process HttpServletRequest");

        }
        if (!(response instanceof HttpServletResponse)) {
            throw new ServletException("Can only process HttpServletResponse");
        }
    }
}
